#include "util.hpp"
#include "ThreadPool.hpp"
#include "Task.hpp"
#include "daemonize.hpp"
class ServerTcp; // 申明一下ServerTcp

class ThreadData
{
public:
    uint16_t clientPort_;
    std::string clientIp_;
    int sock_;
    ServerTcp *this_; // 需要前面申明一下ServerTcp
public:
    ThreadData(uint16_t port, std::string ip, int sock, ServerTcp *ts)
        : clientPort_(port), clientIp_(ip), sock_(sock), this_(ts)
    {
    }
};

void tranService(int sock, const std::string &clientIp, uint16_t clientPort)
{
    assert(sock >= 0);
    assert(!clientIp.empty());
    assert(clientPort >= 1024);

    char inbuffer[BUFFER_SIZE];
    while (true)
    {
        ssize_t s = read(sock, inbuffer, sizeof(inbuffer) - 1);
        if (s > 0)
        {
            inbuffer[s] = '\0'; // 漏写！！！！！
            if (strcasecmp(inbuffer, "quit") == 0)
            {
                logMessage(DEBUG, "client quit -- %s[%d]", clientIp.c_str(), clientPort);
                break;
            }
            for (int i = 0; i < s; i++)
            {
                if (isalpha(inbuffer[i]) && islower(inbuffer[i]))
                {
                    inbuffer[i] = toupper(inbuffer[i]);
                }
            }
            logMessage(DEBUG, "trans after: %s[%d]>>> %s",
                       clientIp.c_str(), clientPort, inbuffer);
            write(sock, inbuffer, strlen(inbuffer));
        }
        else if (s == 0) // s == 0，代表对端关闭
        {
            logMessage(DEBUG, "client quit -- %s[%d]", clientIp.c_str(), clientPort);
            break;
        }
        else
        {
            logMessage(DEBUG, "%s[%d] - read: %s", clientIp.c_str(), clientPort, strerror(errno));
            break;
        }
    }
    // 只要走到这里，一定是client退出了，服务到此结束
    close(sock); // 如果一个进程对应的文件fd，打开了没有被归还，文件描述符泄漏！
    logMessage(DEBUG, "server close %d done", sock);
}
void execCommand(int sock, const std::string &clientIp, uint16_t clientPort)
{
    assert(sock >= 0);
    assert(!clientIp.empty());
    assert(clientPort >= 1024);

    char command[BUFFER_SIZE];
    while (true)
    {
        ssize_t s = read(sock, command, sizeof(command) - 1);
        if (s > 0)
        {
            command[s] = '\0'; // 漏写！！！！！
            if (strcasecmp(command, "quit") == 0)
            {
                logMessage(DEBUG, "client quit -- %s[%d]", clientIp.c_str(), clientPort);
                break;
            }
            std::string safe = command;
            if (std::string::npos != safe.find("rm") || std::string::npos != safe.find("unlink"))
                break;
            FILE *fp = popen(command, "r");
            if (fp == nullptr)
            {
                logMessage(WARNNING, "exec %s failed,because %s", command, strerror(errno));
                break;
            }
            char line[1024];
            memset(line, 0, sizeof line);
            while (fgets(line, sizeof(line) - 1, fp) != nullptr)
            {
                cout << "line size:" << strlen(line) << " line:" << line;
                write(sock, line, strlen(line));
            }
            pclose(fp);
            logMessage(DEBUG, "[%s:%d] exec [%s] ... done", clientIp.c_str(), clientPort, command);
        }
        else if (s == 0) // s == 0，代表对端关闭
        {
            logMessage(DEBUG, "client quit -- %s[%d]", clientIp.c_str(), clientPort);
            break;
        }
        else
        {
            logMessage(DEBUG, "%s[%d] - read: %s", clientIp.c_str(), clientPort, strerror(errno));
            break;
        }
    }
    // 只要走到这里，一定是client退出了，服务到此结束
    close(sock); // 如果一个进程对应的文件fd，打开了没有被归还，文件描述符泄漏！
    logMessage(DEBUG, "server close %d done", sock);
}

static Respond calculator(const Request &req)
{
    Respond res;
    switch (req.op_)
    {
    case '+':
        res.result_ = req.x_ + req.y_;
        break;
    case '-':
        res.result_ = req.x_ - req.y_;
        break;
    case '*':
        res.result_ = req.x_ * req.y_;
        break;
    case '/':
        if (req.y_ == 0)
            res.exitCode_ = -1;
        else
            res.result_ = req.x_ / req.y_;
        break;
    case '%':
        if (req.y_ == 0)
            res.exitCode_ = -2;
        else
            res.result_ = req.x_ % req.y_;
        break;
    default:
        res.exitCode_ = -3;
        break;
    }
    return res;
}
// 9\r\n100 + 200\r\n    9\r\n112 / 200\r\n
void netCap(int sock, const std::string &clientIp, uint16_t clientPort)
{
    assert(sock > 0);
    assert(!clientIp.empty());
    assert(clientPort >= 1024);
    
    std::string inbuffer;
    while (true)
    {
        char buff[1024];
        Request req;
        ssize_t s = read(sock, buff, sizeof(buff) - 1);
        if (s == 0)
        {
            logMessage(NOTICE, "client[%s:%d]close sock,service done", clientIp.c_str(), clientPort);
            break;
        }
        else if (s < 0)
        {
            logMessage(NOTICE, "read client[%s:%d] error,errorcode:%s,errormessage:%s", clientIp.c_str(), clientPort, errno, strerror(errno));
            break;
        }
        // 读取成功
        //  9\r\n100 + 200\r\n    9\r\n112 / 200\r\n
        buff[s] = 0;
        inbuffer += buff;
        // 检查inbuffer是否有完整报文
        // 解码decode：字符串 转 结构体
        uint32_t PackageLen;
        cout<<"inbuffer: "<<inbuffer<<endl;
        std::string package = decode(inbuffer, &PackageLen); // package=100 + 200
        if (PackageLen == 0)
            continue;
        cout<<"package: "<<package<<endl;
        if (req.deserialize(package))
        {
            req.debug();
            Respond res = calculator(req);
            // 解码——反序列化——处理——序列化serialize——加码encode
            std::string respPackage;
            res.serialize(&respPackage);
            respPackage = encode(respPackage, respPackage.size());
            write(sock, respPackage.c_str(), respPackage.size());
        }
    }
}
class ServerTcp
{
public:
    ServerTcp(uint16_t port, std::string ip = "")
        : port_(port), ip_(ip), listensock_(-1), tp_(nullptr)
    {
    }

    void init()
    {
        // 1.创建套接字
        listensock_ = socket(AF_INET, SOCK_STREAM, 0);
        if (listensock_ < 0)
        {
            logMessage(FATAL, "socket create fail————: %s\n", strerror(errno));
            exit(SOCKET_ERR);
        }
                cout<<"12222222222222"<<endl;
        logMessage(DEBUG, "socket create success: %s,listensock_:%d\n",
                   strerror(errno), listensock_);
        // 2.bin绑定
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = PF_INET;
        local.sin_port = htons(port_);
        ip_.empty() ? (local.sin_addr.s_addr = INADDR_ANY) : (inet_aton(ip_.c_str(), &local.sin_addr));
        if (bind(listensock_, (struct sockaddr *)&local, sizeof(local)) < 0)
        {
            logMessage(FATAL, "bind fail————: %s\n", strerror(errno));
            exit(BIND_ERR);
        }
        logMessage(DEBUG, "bind success: %s\n", strerror(errno));
        // 3.设置监听状态
        if (listen(listensock_, 5) < 0)
        {
            logMessage(FATAL, "listen fail————: %s\n", strerror(errno));
            exit(LISTEN_ERR);
        }
        logMessage(DEBUG, "listen success: %s,listensock_:%d\n", strerror(errno), listensock_);
        // 4.加载线程池
        tp_ = ThreadPool<Task>::getInstance(); // 初始化线程池各个值，但是线程队列还未加载线程
    }
    // static void *threadRoutine(void *args)
    // {
    //     pthread_detach(pthread_self());
    //     ThreadData *td = static_cast<ThreadData *>(args);
    //     td->this_->tranService(td->sock_, td->clientIp_, td->clientPort_);
    //     return nullptr;
    // }
    void loop()
    {
        tp_->start(); // 启动线程池，即：加载好了线程队列的线程
        while (true)
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            // 4.服务器获取连接 accept
            int serverSock = accept(listensock_, (struct sockaddr *)&peer, &len);
            if (serverSock < 0)
            {
                logMessage(WARNNING, "accept fail————: %s[%d]\n", strerror(errno), serverSock);
                std::cout << "listensock_:" << listensock_ << std::endl;
                sleep(1);
                continue;
            }
            // 5.获取客户端基本信息。
            uint16_t peerPort = ntohs(peer.sin_port);
            std::string peerIp = inet_ntoa(peer.sin_addr);
            logMessage(DEBUG, "accept success: %s | %s[%d],socket fd: %d\n",
                       strerror(errno), peerIp.c_str(), peerPort, serverSock);
            // 6.提供服务 读取并处理任务(线程池接入后就可以不用再现场创建线程了)
            // ThreadData* td=new ThreadData(peerPort,peerIp,serverSock,this);
            // pthread_t tid;
            // pthread_create(&tid,nullptr,threadRoutine,td);
            Task t(serverSock, peerPort, peerIp, netCap);
            tp_->push(t);
        }
    }

private:
    int listensock_;
    uint16_t port_;
    std::string ip_;
    // 接入线程池
    ThreadPool<Task> *tp_; // 指针都是内置类型，默认构造函数不做处理
};
void Usage(std::string proc)
{
    std::cerr << "Usage:\n\t" << proc << " port ip" << std::endl;
    std::cerr << "exmaple:\n\t" << proc << " 8080 127.0.0.11\n"
              << std::endl;
}
// ./serverTcp local_port local_ip
// ./serverTcp 8080
int main(int argc, const char *argv[])
{
    if (argc != 3 && argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);
    std::string ip;
    if (argc == 3)
    {
        ip = argv[2];
    }
    // daemonize();
    ServerTcp svr(port, ip);
    // Log log;
    // log.enable();
                //cout<<"1111"<<endl;
    svr.init();
    svr.loop();
    return 0;
}